
#include "bookmark-tree-store.h"
#include "bookmark.h"

static void bookmark_tree_store_drag_source_init (GtkTreeDragSourceIface *iface);
static void bookmark_tree_store_drag_dest_init (GtkTreeDragDestIface *iface);

static gboolean
     bookmark_tree_store_row_drop_possible (GtkTreeDragDest  *drag_dest,
                                            GtkTreePath      *dest_path,
                                            GtkSelectionData *selection_data);


G_DEFINE_TYPE_WITH_CODE (BookmarkTreeStore, bookmark_tree_store, 
                         GTK_TYPE_TREE_STORE,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
                                           bookmark_tree_store_drag_source_init)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_DEST,
                                           bookmark_tree_store_drag_dest_init))


static void
bookmark_tree_store_class_init (BookmarkTreeStoreClass *klass)
{
	GObjectClass *object_class = G_OBJECT_CLASS (klass);

}


static void
bookmark_tree_store_drag_source_init (GtkTreeDragSourceIface *iface)
{
}

static void
bookmark_tree_store_drag_dest_init (GtkTreeDragDestIface *iface)
{
    iface->row_drop_possible = bookmark_tree_store_row_drop_possible;
}

enum {
    COLUMN_NAME,
    COLUMN_ENTRY,
    COLUMNS_BM
};

static void
bookmark_tree_store_init (BookmarkTreeStore *self)
{
	GType types[COLUMNS_BM];

	types[COLUMN_NAME] = G_TYPE_STRING;
	types[COLUMN_ENTRY] = G_TYPE_POINTER;

    gtk_tree_store_set_column_types (GTK_TREE_STORE (self),
                                     COLUMNS_BM, types);
}

GtkListStore*
bookmark_tree_store_new (void)
{
    return g_object_new (BOOKMARK_TYPE_TREE_STORE, NULL);
}


static gboolean
bookmark_tree_store_row_drop_possible (GtkTreeDragDest  *drag_dest,
                                       GtkTreePath      *dest_path,
                                       GtkSelectionData *selection_data)
{
    GtkTreeModel *src_model = NULL;
    GtkTreePath *src_path = NULL;
    GtkTreePath *tmp = NULL;
    gboolean retval = FALSE;
    GtkTreeIter iter;
    GNode *src_node, *dst_node;
    gftp2_bookmark *src_bm, *dst_bm;
  
    if (!gtk_tree_get_row_drag_data (selection_data,
                                     &src_model,
                                     &src_path))
        goto out;

/*
    fprintf (stderr, "%s -to- %s", 
             gtk_tree_path_to_string (src_path), 
             gtk_tree_path_to_string (dest_path));
*/
    
    /* can only drag to ourselves */
    if (src_model != GTK_TREE_MODEL (drag_dest))
        goto out;

    /* Can't drop into ourself. */
    if (gtk_tree_path_is_ancestor (src_path,
                                   dest_path))
        goto out;

    /* Can't drop if dest_path's parent doesn't exist */
    if (gtk_tree_path_get_depth (dest_path) > 1)
    {
        tmp = gtk_tree_path_copy (dest_path);
        gtk_tree_path_up (tmp);
        
        if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_dest),
                                      &iter, tmp))
            goto out;

        gtk_tree_model_get (src_model, &iter, /* src_model == dst_model */
                            COLUMN_ENTRY, &dst_node,
                            -1);
        g_assert (dst_node);
        dst_bm = (gftp2_bookmark *)dst_node->data;
        /* can't drag an item into a non-folder */
        if (!dst_bm->is_folder)
            goto out;

        gtk_tree_model_get_iter (src_model, &iter, src_path);
        gtk_tree_model_get (src_model, &iter, 
                            COLUMN_ENTRY, &src_node,
                            -1);
        g_assert (src_node);
        src_bm = (gftp2_bookmark *)src_node->data;
        /* can't drag folder into a folder */
        if (src_bm->is_folder)
            goto out;
    }


    /* Can otherwise drop anywhere. */
    retval = TRUE;

out:
    /* fprintf (stderr, " %s\n", retval ? "Can drop" : "Can't drop"); */

    if (src_path)
        gtk_tree_path_free (src_path);
    if (tmp)
        gtk_tree_path_free (tmp);

    return retval;
}
